[S05E05] Observable & RxJS in Angular
https://www.youtube.com/watch?v=DuSs1zVVSko&list=PL9LUW6O9WZqgUMHwDsKQf3prtqVvjGZ6S&index=18
本集由Kevin大大講解
Observable in Angular
今天的主題@Component({
selector: 'async-observable-pipe',
template: `<div>
<code> observable | async</code>:
// 會去subscribe一個Observable或Promise^^^^^
Time: {{ time | async }}</div>`
})
export class AsyncObservablePipeComponent {
time = new Observable(observer =>
^^^^ 當time改變的時候,async pipe就會標記為需要cd(Change Detect)
setInterval(() => observer.next(new Date().toString()), 1000)
);
}
Router events
import { Router, NavigationStart } from '@angular/router';
import { filter } from 'rxjs/operators';
@Component({
selector: 'app-routable',
templateUrl: './routable.component.html',
styleUrls: ['./routable.component.css']
})
export class Routable1Component implements OnInit {
navStart: Observable<NavigationStart>;
constructor(private router: Router) {
// Create a new Observable that publishes only the NavigationStart event
this.navStart = router.events.pipe(
^^^^^^ 不會停止
filter(evt => evt instanceof NavigationStart)
) as Observable<NavigationStart>;
^^^^^^^^^^^^^^^^^^^^^^^^^^ NavigationStart是個Observable
}
ngOnInit() {
this.navStart.subscribe(evt => console.log('Navigation Started!'));
^^^^^^^^^ 取到NavigationStart就能subscribe
}
}
ActivatedRoute,目前路由的位址
import { ActivatedRoute } from '@angular/router';
@Component({
selector: 'app-routable',
templateUrl: './routable.component.html',
styleUrls: ['./routable.component.css']
})
export class Routable2Component implements OnInit {
constructor(private activatedRoute: ActivatedRoute) {}
// https://angular.tw/api/router/ActivatedRoute
// ActivatedRoute 很多屬性都是Observable
ngOnInit() {
this.activatedRoute.url
^^^ url: Observable<UrlSegment[]>
.subscribe(url => console.log('The URL changed to: ' + url));
}
}
// ActivatedRoute常用情境:
// 例用 params: Observable<Params>
// 在主檔取得id(主鍵),再進入明細表
valueChanges: Observable<any>
statusChanges: Observable<any>
訂閱可觀察的表單控制元件屬性是在元件類中觸發應用邏輯的途徑之一
import { FormGroup } from '@angular/forms';
@Component({
selector: 'my-component',
template: 'MyComponent Template'
})
export class MyComponent implements OnInit {
nameChangeLog: string[] = [];
heroForm: FormGroup;
ngOnInit() {
this.logNameChange();
}
logNameChange() {
const nameControl = this.heroForm.get('name');
nameControl.valueChanges.forEach(
(value: string) => this.nameChangeLog.push(value)
);
}
}
export class AppComponent {
apiUrl = 'https://jsonplaceholder.typicode.com/posts';
items$ = this.http.get(this.apiUrl);
constructor(private http: HttpClient){}
明明是同樣的items$
但如果寫2次,後端就會要2次,怎麼改善呢?
{{ items$ | async | json }}
{{ items$ | async | json }}
<div *ngIf="items$ | async as items">
^^^^^^^^^^^^^^ 當值取到時,會存放到items變數
{{ items | json }}
{{ items | json }}
<div>
RouterModule.forRoot(
[
{ path: 'profile', component: ProfileComponent },
{ path: 'profile/:id', component: ProfileComponent },
^^^^用ActivatedRoute的params或paramMap取
{ path: '', component: HomeComponent}
],
{
enableTracing: true
} ^^^^^^^^^^^^^^^^^^^ 這個也是用Observable來實作
import { tap } from 'rxjs/operators';
export class ProfileComponent implements OnInit, OnDestroy {
sub;
constructor(
private router: Router,
private route: ActivatedRoute, // 使用方式差不多
private http: HttpClient
){
// 1. 示範 Router
this.sub = this.router.events.subscribe(console.log);
^^^^^^ 所以events應該是Observable或Promise
// 查一下文件,https://angular.tw/api/router/Router
// 所以是 events: Observable<Event>
// An event stream for routing events in this NgModule.
// 2. 示範 ActivatedRoute
// 常見用法:利用ActivatedRoute.paramMap取得params中的id,再向後端要該id的資料
this.route.paramMap
^^^^^^^^ paramMap: Observable<ParamMap>
// https://angular.tw/api/router/ActivatedRoute#paramMap
.pipe(mergeMap(params =>
^^^^^^^^ https://ithelp.ithome.com.tw/articles/10188387
// https://rxjs-dev.firebaseapp.com/api/operators/mergeMap
// mergeMap 吐出來的應該也是一個 Observable
this.http.get(`https://jsonplaceholder.typicode.com/users/${params.get('id')}`)))
.subscribe(data => console.log(data));
this.route.paramMap.subscribe(params => console.log(params));
// 3. tap operator
// https://rxjs-dev.firebaseapp.com/api/operators/tap
// tap<T>(nextOrObserver?: PartialObserver<T>): MonoTypeOperatorFunction<T>
this.route.paramMap
.pipe(tap(params => console.log(params.get('id'))))
.subscribe(params => console.log(params));
}
ngOnDestroy(){
this.sub.unsubscribe(); // 不確定this.router.events會不會自己中止
}